#ifndef SKIP_LIST_ON_RAFT_CLERK_H
#define SKIP_LIST_ON_RAFT_CLERK_H

#include <arpa/inet.h>
#include <netinet/in.h>
#include <raftServerRpcUtil.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <cerrno>
#include <string>
#include <vector>
#include "kvServerRPC.pb.h"
#include "mprpcconfig.h"

// Clerk类：分布式KV系统中的客户端代理类
// 作用：作为客户端（用户/应用）与KV服务器集群交互的中间层，封装与集群通信的细节
class Clerk {
public:
    Clerk();
public:
    // 对外暴露的核心接口和初始化方法
    // 初始化函数：从配置文件加载集群信息（如服务器节点的IP和端口），建立与节点的连接
    void Init(std::string configFileName);

    // 查询操作：根据key从KV服务器获取对应的value
    std::string Get(std::string key);

    // 插入操作：向KV服务器插入key-value对（若key存在则覆盖）
    void Put(std::string key, std::string value);

    // 追加操作：向KV服务器的key对应的value后追加内容（若key不存在则新建）
    void Append(std::string key, std::string value);

private:
    // 生成客户端唯一标识（clientId）的辅助函数
    // 实现：通过多次调用rand()生成随机字符串，确保不同客户端的标识唯一
    std::string Uuid() {
        return std::to_string(rand()) + std::to_string(rand()) + std::to_string(rand()) + std::to_string(rand());
    }  //用于返回随机的clientId

    // Put和Append操作的公共逻辑封装（内部辅助函数）
    // 参数：key-键，value-值，op-操作类型（"Put"或"Append"）
    void PutAppend(std::string key, std::string value, std::string op);

private:
    std::vector<std::shared_ptr<raftServerRpcUtil>>
        m_servers;              // 存储所有KV服务器节点的RPC连接工具 全部初始化为-1，表示没有连接上
    std::string m_clientId;     // 客户端唯一标识
    int m_requestId;            // 请求序列号,每个客户端的请求按序号递增，服务器可通过(clientId + requestId)唯一标识一个请求，防止重复处理
    int m_recentLeaderId;       // 最近的领导者节点ID
};

#endif  // SKIP_LIST_ON_RAFT_CLERK_H